﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
//using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

using LuckyBingoRcon.Matches;
using LuckyBingoRcon.Messages;
using LuckyBingoRcon.Players;
using LuckyBingoRcon.Utilities;

namespace LuckyBingoRcon
{
    public partial class RconForm : Form
    {
        private delegate void VoidDel();
        private delegate void StringDel(string s);
        private delegate void ColorDel(Color c);
        private delegate void TBoxDel(TextBox tb, Color c);

        private static LuckyBingoRcon.Utilities.DebugMessageViewer console = new LuckyBingoRcon.Utilities.DebugMessageViewer();
        public static LuckyBingoRcon.Utilities.DebugMessageViewer Console
        {
            get { return console; }
        }

        private readonly string configFolder = Application.StartupPath + "\\Configs";
        private readonly string configFile = Application.StartupPath + "\\Configs\\Servers.xml";

        private string cellContents = string.Empty;
        private int clickIndex = -1;
        private string selectedPlayer = null;
        private TextBox textbox = null;
        private List<Match> matches = new List<Match>();
        private List<LuckyBingoRcon.Messages.Message> messages = new List<LuckyBingoRcon.Messages.Message>();
        private bool enableTabs = false;
        private bool updateServer = false;
        private int delay = 5000;
        private string lastMessage = String.Empty;

        private Dictionary<string, Color> charConverts = new Dictionary<string, Color>();
        private List<string> customCommands = new List<string>();
        private int customCommandCounter = -1;

        private RConV2 rcon = new RConV2();
        GametypeLookup game = new GametypeLookup();
        MapLookup map = new MapLookup();
        TeamLookup teams = new TeamLookup();

        public RconForm()
        {
            InitializeComponent();
            LoadXML();
            console.DebugForm = this.debugConsoleControl1;
            this.charConverts.Add("^0", Color.Black);
            this.charConverts.Add("^1", Color.Red);
            this.charConverts.Add("^2", Color.Green);
            this.charConverts.Add("^3", Color.FromArgb(230,168,14));
            this.charConverts.Add("^4", Color.Blue);
            this.charConverts.Add("^5", Color.Cyan);
            this.charConverts.Add("^6", Color.Magenta);
            this.charConverts.Add("^7", Color.LightGray);
            this.charConverts.Add("^8", Color.Gray);
            this.charConverts.Add("^9", Color.Brown);

			rcon.OnCusomCommandResponse += new EventHandler<Commands.Events.CustomCommandEventArgs>(customCommand_OnResponse);
        }

        #region Server Login Settings
        private void listBoxServers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listBoxServers.SelectedIndex.Equals(-1))
            {
                this.buttonAddServer.Enabled = false;
                this.buttonRemoveServer.Enabled = false;
                this.buttonUpdateServerName.Enabled = false;
            }
            else
            {
                this.buttonAddServer.Enabled = true;
                this.buttonRemoveServer.Enabled = true;
                if (!string.IsNullOrEmpty(this.textBoxIP.Text) && !string.IsNullOrEmpty(this.textBoxPort.Text) && !string.IsNullOrEmpty(this.textBoxPWord.Text))
                    this.buttonUpdateServerName.Enabled = true;
            }
        }

        private void listBoxServers_DoubleClick(object sender, EventArgs e)
        {
            int index = this.listBoxServers.SelectedIndex;
            if (!index.Equals(-1))
            {
                FileInfo finfo = new FileInfo(configFile);
                if (finfo.Exists.Equals(true))
                {
                    XmlDocument doc = new XmlDocument();
                    try
                    {
                        doc.Load(configFile);
                    }
                    catch
                    {
                        return;                         // File is open by the writer, return                        
                    }
                    XmlNodeList nl = doc.GetElementsByTagName("Server");
                    foreach (XmlNode node in nl)
                    {
                        if (node.Attributes.Item(0).Value.Equals(this.listBoxServers.SelectedItem.ToString()))
                        {
                            if (node.ChildNodes.Count.Equals(3))
                            {
                                this.textBoxIP.Text = node.ChildNodes[0].InnerText;
                                this.textBoxPort.Text = node.ChildNodes[1].InnerText;
                                this.textBoxPWord.Text = node.ChildNodes[2].InnerText;
                            }
                        }
                    }
                }
            }
        }

        private void LoadXML()
        {
            this.listBoxServers.Items.Clear();
            FileInfo finfo = new FileInfo(configFile);
            if (finfo.Exists.Equals(true))
            {
                XmlDocument doc = new XmlDocument();
                try
                {
                    doc.Load(configFile);
                }
                catch
                {
                    Console.WriteLine("Could not open the server list file");
                    // File is open by the writer, return
                    return;
                }
                XmlNodeList nl = doc.GetElementsByTagName("Server");
                foreach (XmlNode node in nl)
                {
                    if (!this.listBoxServers.Items.Contains(node.Attributes.Item(0).Value.ToString()))
                        this.listBoxServers.Items.Add(node.Attributes.Item(0).Value.ToString());
                }
            }
        }

        private void buttonAddServer_Click(object sender, EventArgs e)
        {
            Point loc = this.Location;
            using (InputBox ib = new InputBox())
            {
                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
            }
            InputResult ir = InputBox.ShowBox("Server Name", null, loc);
            if (ir != null)
            {
                if (ir.Message.Length.Equals(0))
                {
                    MessageBox.Show("Server name required!", "Input Error!");
                    return;
                }
                else if (this.listBoxServers.Items.Contains(ir.Message))
                {
                    MessageBox.Show("Duplicate server name entered. Try again", "Input Error!");
                    return;
                }
            }
            else
            {
                MessageBox.Show("Server name required!", "Input Error!");
                return;
            }
            FileInfo finfo = new FileInfo(configFile);
            XmlDocument doc = new XmlDocument();
            if (!finfo.Exists)
            {
                XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
                doc.AppendChild(dec);
                XmlElement root = doc.CreateElement("LuckyServer");
                doc.AppendChild(root);
                XmlElement server = doc.CreateElement("Server");
                server.SetAttribute("label", ir.Message);
                XmlElement host = doc.CreateElement("host");
                host.InnerText = this.textBoxIP.Text;
                XmlElement port = doc.CreateElement("port");
                port.InnerText = this.textBoxPort.Text;
                XmlElement password = doc.CreateElement("password");
                password.InnerText = this.textBoxPWord.Text;
                server.AppendChild(host);
                server.AppendChild(port);
                server.AppendChild(password);
                root.AppendChild(server);
                if (!Directory.Exists(configFolder))
                    Directory.CreateDirectory(configFolder);
                doc.Save(new FileStream(configFile, FileMode.Create));
                Console.WriteLine("Server list created with its first entry");
            }
            else
            {
                doc.Load(configFile);
                XmlElement server = doc.CreateElement("Server");
                server.SetAttribute("label", ir.Message);
                XmlElement host = doc.CreateElement("host");
                host.InnerText = this.textBoxIP.Text;
                XmlElement port = doc.CreateElement("port");
                port.InnerText = this.textBoxPort.Text;
                XmlElement password = doc.CreateElement("password");
                password.InnerText = this.textBoxPWord.Text;
                server.AppendChild(host);
                server.AppendChild(port);
                server.AppendChild(password);
                doc.DocumentElement.AppendChild(server);
                if (!Directory.Exists(configFolder))
                    Directory.CreateDirectory(configFolder);
                doc.Save(new FileStream(configFile, FileMode.Create));
                Console.WriteLine("Server added to server list");
            }
            this.listBoxServers.Items.Add(ir.Message);
        }

        private void buttonUpdateServerName_Click(object sender, EventArgs e)
        {
            int index = this.listBoxServers.SelectedIndex;
            if (!index.Equals(-1))
            {
                Point loc = this.Location;
                using (InputBox ib = new InputBox())
                {
                    loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
                }
                InputResult ir = InputBox.ShowBox("Server Name", this.listBoxServers.SelectedItem.ToString(), loc);
                if (ir != null)
                {
                    if (ir.Message.Length > 0)
                    {
                        this.listBoxServers.Items[index] = ir.Message;
                    }
                    else if (this.listBoxServers.Items.Contains(ir.Message))
                    {
                        MessageBox.Show("Server name already exists!", "Input Error!");
                        return;
                    }
                    else
                    {
                        MessageBox.Show("Server name required!", "Input Error!");
                        return;
                    }
                }
                else
                {
                    MessageBox.Show("Server name required!", "Input Error!");
                    return;
                }
                FileInfo finfo = new FileInfo(configFile);
                if (finfo.Exists)
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(configFile);
                    XmlNodeList nl = doc.GetElementsByTagName("Server");
                    if (nl.Count > index)
                    {
                        nl.Item(index).Attributes.Item(0).Value = ir.Message;
                        nl.Item(index).ChildNodes[0].InnerText = this.textBoxIP.Text;
                        nl.Item(index).ChildNodes[1].InnerText = this.textBoxPort.Text;
                        nl.Item(index).ChildNodes[2].InnerText = this.textBoxPWord.Text;
                        doc.Save(new FileStream(configFile, FileMode.Create));
                        Console.WriteLine("Server list updated");
                    }
                    else
                        MessageBox.Show("Server list file is corrupt!", "File Error!");
                }
                else
                    MessageBox.Show("Server list file does not exist!", "File Error!");
            }
        }

        private void buttonRemoveServer_Click(object sender, EventArgs e)
        {
            int index = this.listBoxServers.SelectedIndex;
            if (!index.Equals(-1))
            {
                XmlDocument doc = new XmlDocument();
                FileInfo file = new FileInfo(configFile);
                if (file.Exists)
                {
                    try
                    {
                        doc.Load(configFile);
                    }
                    catch
                    {
                        MessageBox.Show("Server list file is open by another program.\nTry again in a minute.", "File Error!");
                        return;
                    }
                    if (doc.HasChildNodes)
                    {
                        try
                        {
                            XmlNodeList nl = doc.GetElementsByTagName("Server");
                            doc.DocumentElement.RemoveChild(nl.Item(index));
                            doc.Save(new FileStream(configFile, FileMode.Create));
                            this.listBoxServers.Items.RemoveAt(index);
                            Console.WriteLine("Server removed from server list");
                        }
                        catch { }
                    }
                }
            }
        }
        #endregion

        #region Connections
        private void textBoxIP_TextChanged(object sender, EventArgs e)
        {
            string text = textBoxIP.Text;
            IPAddress addr;
            if (System.Net.IPAddress.TryParse(text, out addr))
            {
                this.SetTextBoxColor(sender as TextBox, Color.LightGreen);
                this.ClearStatus();
                if (string.IsNullOrEmpty(this.textBoxIP.Text) == false && string.IsNullOrEmpty(this.textBoxPort.Text) == false && string.IsNullOrEmpty(this.textBoxPWord.Text) == false)
                {
                    this.buttonConnect.Enabled = true;
                    this.buttonAddServer.Enabled = true;
                }
                else
                {
                    this.buttonConnect.Enabled = false;
                    this.buttonAddServer.Enabled = false;
                }
            }
            else
            {
                this.SetStatus("Invalid IP Address");
                this.SetStatusTextColor(Color.Red);
                this.buttonConnect.Enabled = false;
                this.buttonAddServer.Enabled = false;
            }
        }

        private void textBoxPort_TextChanged(object sender, EventArgs e)
        {
            string text = textBoxPort.Text;
            int port;
            if (int.TryParse(text, out port))
            {
                if (port < 1 || 65535 < port)
                {
                    this.SetStatus(port + " is not a valid port number");
                    this.SetStatusTextColor(Color.Red);
                    this.buttonConnect.Enabled = false;
                    this.buttonAddServer.Enabled = false;
                }

                this.SetTextBoxColor(sender as TextBox, Color.LightGreen);
                this.ClearStatus();
                if (string.IsNullOrEmpty(this.textBoxIP.Text) == false && string.IsNullOrEmpty(this.textBoxPort.Text) == false && string.IsNullOrEmpty(this.textBoxPWord.Text) == false)
                {
                    this.buttonConnect.Enabled = true;
                    this.buttonAddServer.Enabled = true;
                }
                else
                {
                    this.buttonConnect.Enabled = false;
                    this.buttonAddServer.Enabled = false;
                }
            }
            else
            {
                this.SetStatus("Invalid Port");
                this.SetStatusTextColor(Color.Red);
                this.buttonConnect.Enabled = false;
                this.buttonAddServer.Enabled = false;
            }
        }

        private void textBoxPWord_TextChanged(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.textBoxIP.Text) == false && string.IsNullOrEmpty(this.textBoxPort.Text) == false && string.IsNullOrEmpty(this.textBoxPWord.Text) == false)
            {
                this.buttonConnect.Enabled = true;
                this.buttonAddServer.Enabled = true;
            }
            else
            {
                this.buttonConnect.Enabled = false;
                this.buttonAddServer.Enabled = false;
            }            
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            if (!rcon.Connected)
            {
                this.Enabled = false;
                bool done = false;
                System.Threading.ThreadPool.QueueUserWorkItem((x) =>
                {
                    using (var splash = new splashForm())
                    {
                        Point loc = this.Location;
                        loc.Offset((this.Width / 2) - (splash.Width / 2), (this.Height / 2) - (splash.Height / 2));
                        splash.Location = loc;
                        splash.Show();
                        while (!done)
                            Application.DoEvents();
                        splash.Close();
                    }
                }); 
                try
                {
                    string remoteHost = textBoxIP.Text;
                    int port = int.Parse(textBoxPort.Text);
                    string password = textBoxPWord.Text;

                    bool connected = rcon.Connect(remoteHost, port, password);
                    if (connected)
                    {
                        done = true; 
                        Console.WriteLine("Connected to " + remoteHost.ToString());
                        this.SetStatus("Connected");
                        this.SetStatusTextColor(Color.Green);
                        this.textBoxIP.Enabled = false;
                        this.textBoxPort.Enabled = false;
                        this.textBoxPWord.Enabled = false;
                        this.buttonConnect.Text = "Disconnect";

                        mapCheckTimer_Tick(sender, e);
                        /*this.mapCheckTimer.Enabled = true;*/
                        rcon.GetServerName();
                        /*queryServer_Tick(sender, e);
                        this.queryServer.Enabled = true;*/
                        queryServerState_Tick(sender, e);
                        this.queryServerState.Enabled = true;
                        queryPlayers_Tick(sender, e);
                        this.queryPlayers.Enabled = true;
                        this.checkAdmins.Enabled = true;
                
                        this.labelAdminStatus.Text = "Connected!";
                        this.labelAdminStatus.ForeColor = Color.Green;

                        if (MessageBox.Show("Do you want to be put in the queue for super admin permissions?\nYou will need a GameServers.com login for the running server.", "Super Admin", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            Point loc = this.Location;
                            using (InputBox ib = new InputBox())
                            {
                                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
                            }
                            InputResult ir = InputBox.ShowBox("GameServers Login", null, loc);
                            if (ir != null)
                            {
                                if (ir.Message.Length > 0 && ir.Password.Length > 0)
                                {
                                    WebBrowser b = new WebBrowser();
                                    b.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(AuthenticationCheck);
                                    string postData = string.Format("query_string=&username={0}&password={1}&x=32&y=13", ir.Message, ir.Password);

                                    //  we are encoding the postData to a byte array
                                    b.Navigate("https://my.gameservers.com/?logout=1", "", System.Text.ASCIIEncoding.ASCII.GetBytes(postData), "Content-Type: application/x-www-form-urlencoded\r\n");
                                }
                            }
                        }
                        else
                        {
                            this.labelAdminStatus.Text = "Regular Admin";
                            this.labelAdminStatus.ForeColor = Color.Orange;
                        }
                        //this.timerQueue.Enabled = true;
                    }
                    else
                    {
                        done = true;
                        this.mapCheckTimer.Enabled = false;
                        rcon.SetTimeStampCheck(false);
                        Console.WriteLine("Could not connect to" + remoteHost.ToString());
                        this.SetStatus("Connection failed");
                        this.SetStatusTextColor(Color.Red);
                    }
                }
                catch (Exception)
                {
                    done = true;
                    this.mapCheckTimer.Enabled = false;
                    rcon.SetTimeStampCheck(false);
                    this.SetStatus("Connection failed");
                    this.SetStatusTextColor(Color.Red);
                }
                this.Enabled = true;
            }
            else
            {
                rcon.SetTimeStampCheck(false);
                this.optionTabs.SelectedIndex = 1;
                if (this.buttonUpdateMessage.Text.Equals("Stop Rotation"))
                    this.buttonUpdateMessage_Click(sender, e);
                if (this.buttonUpdateRotation.Text.Equals("Stop Rotation"))
                    this.buttonUpdateRotation_Click(sender, e);
                this.textBoxIP.Enabled = true;
                this.textBoxPort.Enabled = true;
                this.textBoxPWord.Enabled = true;
                this.SetStatus("Disonnected from " + this.textBoxIP.Text);
                this.SetStatusTextColor(Color.Green);
                Console.WriteLine("Disconnected from " + textBoxIP.Text);

                this.mapCheckTimer.Enabled = false;
                this.queryServer.Enabled = false;
                this.queryServerState.Enabled = false;
                this.queryPlayers.Enabled = false;
                this.checkAdmins.Enabled = false;
                rcon.SetTimeStampCheck(false);

                this.timerQueue.Enabled = false;

                this.buttonConnect.Enabled = true;
                this.updateServer = false;
                this.labelAdminStatus.Text = "Not Connected!";
                this.labelAdminStatus.ForeColor = Color.Red;
                this.buttonConnect.Text = "Connect";

                rcon.Reset();                
            }
        }
        #endregion

        #region Super Admin Authentication
        private void AuthenticationCheck(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            WebBrowser b = sender as WebBrowser;
            if (b.DocumentText.Contains("logout"))
            {
                MessageBox.Show("You have authenicated with the server's GameServers credentials.\nYou can become a super admin", "Authentication Successful");
                rcon.SetTimeStampCheck(true);
                checkAdmins_Tick(sender, e);
                this.checkAdmins.Enabled = true;
                Console.WriteLine("Authenticated to become a Super Admin");
            }
            else
            {
                Console.WriteLine("Authentication for Super Admin failed");
                if (MessageBox.Show("You have entered incorrect GameServers credentials.\nAttempt to authenticate again?", "Authentication Successful", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    Point loc = this.Location;
                    using (InputBox ib = new InputBox())
                    {
                        loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
                    }
                    InputResult ir = InputBox.ShowBox("GameServers Login", null, loc);
                    if (ir != null)
                    {
                        if (ir.Message.Length > 0 && ir.Password.Length > 0)
                        {
                            string postData = string.Format("query_string=&username={0}&password={1}&x=32&y=13", ir.Message, ir.Password);

                            //  we are encoding the postData to a byte array
                            b.Navigate("https://my.gameservers.com/?logout=1", "", System.Text.ASCIIEncoding.ASCII.GetBytes(postData), "Content-Type: application/x-www-form-urlencoded\r\n");
                        }
                    }
                }
            }
        }
        #endregion

        #region Update Server Information (Top of Form)
        private void queryServerState_Tick(object sender, EventArgs e)
        {
            ServerState state = rcon.GetServerState();
            if (state != null)
            {
                if (state.ServerName != null)
                    this.labelServerName.Text = state.ServerName;
                if (state.CurrentMap != null && state.CurrentMap.PrettyName != null)
                    this.labelCurrentMap.Text = state.CurrentMap.PrettyName;
                if (state.GameType != null && state.GameType.GameName != null)
                    this.labelCurrentGametype.Text = state.GameType.GameName.Replace("&", "&&");
                if (state.NextMap != null)
                    this.labelNextMap.Text = state.NextMap;
                if (state.NextGameType != null)
                    this.labelNextGametype.Text = state.NextGameType.Replace("&", "&&");
                if (state.MapSwitched.Equals(true))
                {
                    Match nextMatch = this.listBoxMatches.Items[0] as Match;
                    this.listBoxMatches.Items.Add(this.listBoxMatches.Items[0]);
                    this.listBoxMatches.Items.RemoveAt(0);
                    rcon.SetMapSwitchedState(false);
                    Console.WriteLine(nextMatch + " up next");
                }
            }
        }
        #endregion

        


        // Relatively comfortable with the items below //

        #region Message Rotation
        private void buttonUpdateMessageRotation_Click(object sender, EventArgs e)
        {
            if (this.buttonUpdateMessageRotation.Text.Equals("Start Rotation"))
            {
                this.messageDisplayTimer.Enabled = false;
                this.messageDisplayTimer.Stop();
                List<LuckyBingoRcon.Messages.Message> messages = new List<LuckyBingoRcon.Messages.Message>();
                LuckyBingoRcon.Messages.Message mess = new LuckyBingoRcon.Messages.Message();
                foreach (DataGridViewRow row in this.listBoxMessages.Rows)
                    messages.Add(mess.FromRow(row));
                if (messages.Count > 0)
                {
                    rcon.setMessageLists(messages);
                    this.messageDisplayTimer.Enabled = true;
                    this.messageDisplayTimer.Start();
                    this.buttonUpdateMessageRotation.Text = "Stop Rotation";
                    this.buttonAddMessage.Enabled = false;
                    this.buttonRemoveMessage.Enabled = false;
                    this.textboxMessage.Enabled = false;
                    this.textBoxMessageDuration.Enabled = false;
                    this.comboBoxGametypeSelect.Enabled = false;
                    this.comboBoxMapSelect.Enabled = false;
                    this.listBoxMessages.Enabled = false;
                    this.buttonLoadMessageRotation.Enabled = false;
                    this.buttonMessageMoveDown.Enabled = false;
                    this.buttonMessageMoveUp.Enabled = false;
                    this.buttonUpdateMessage.Enabled = false;
                    this.textBoxNextMap.Enabled = false;
                    this.textBoxNextMapDelay.Enabled = false;
                    Console.WriteLine("Message rotation started");
                    if (!this.buttonUpdateMessageRotation.Text.Equals("Stop Rotation") && !this.buttonUpdateRotation.Text.Equals("Stop Rotation"))
                        this.buttonConnect.Enabled = true;
                    else
                        this.buttonConnect.Enabled = false;
                }
            }
            else if (this.buttonUpdateMessageRotation.Text.Equals("Stop Rotation"))
            {
                this.messageDisplayTimer.Enabled = false;
                this.messageDisplayTimer.Stop();
                this.buttonUpdateMessageRotation.Text = "Start Rotation";
                this.textboxMessage.Enabled = true;
                this.textBoxMessageDuration.Enabled = true;
                this.comboBoxGametypeSelect.Enabled = true;
                this.comboBoxMapSelect.Enabled = true;
                this.listBoxMessages.Enabled = true;
                this.buttonLoadMessageRotation.Enabled = true;
                this.buttonMessageMoveDown.Enabled = true;
                this.buttonMessageMoveUp.Enabled = true;
                this.buttonUpdateMessage.Enabled = true;
                this.textBoxNextMap.Enabled = true;
                this.textBoxNextMapDelay.Enabled = true;
                Console.WriteLine("Message rotation stopped");
                if (!this.buttonUpdateMessageRotation.Text.Equals("Stop Rotation") && !this.buttonUpdateRotation.Text.Equals("Stop Rotation"))
                    this.buttonConnect.Enabled = true;
                else
                    this.buttonConnect.Enabled = false;
            }
        }

        private void buttonSaveMessageRotation_Click(object sender, EventArgs e)
        {
            SaveFileDialog fdlg = new SaveFileDialog();
            fdlg.InitialDirectory = Directory.GetCurrentDirectory();
            fdlg.RestoreDirectory = true;
            fdlg.Title = "Select a Location to Save Rotation File";
            fdlg.DefaultExt = "mer";
            fdlg.Filter = "Message Rotation files (*.mer)|*.mer";
            fdlg.FilterIndex = 1;
            fdlg.CheckFileExists = false;
            fdlg.CheckPathExists = true;
            if (fdlg.ShowDialog() == DialogResult.OK)
            {
                bool success = false;
                bool fileValid = false;
                try
                {
                    new FileInfo(fdlg.FileName);
                    fileValid = true;
                }
                catch { }
                if (fileValid)
                {
                    // Save contents of listbox to file
                    List<LuckyBingoRcon.Messages.Message> args = new List<LuckyBingoRcon.Messages.Message>(this.listBoxMessages.Rows.Count);
                    string arg = string.Empty;
                    int duration = -1;
                    LuckyBingoRcon.Messages.Message message = new LuckyBingoRcon.Messages.Message();
                    foreach (DataGridViewRow entry in this.listBoxMessages.Rows)
                    {
                        if (!string.IsNullOrEmpty(entry.Cells[0].Value.ToString()) && int.TryParse(entry.Cells[1].Value.ToString(), out duration) == true && duration > 0 && entry.Cells[2].Value != null && entry.Cells[3].Value != null)
                        {
                            args.Add(message.FromRow(entry));
                        }
                    }
                    success = rcon.saveMessageRotationConfig(args, fdlg.FileName);
                }
                if (success)
                {
                    FileInfo fInfo = new FileInfo(fdlg.FileName);
                    fInfo.IsReadOnly = true;
                    this.SetStatus(DateTime.Now.ToLongTimeString() + ": File Successfully Written to File");
                    this.SetStatusTextColor(Color.Green);
                    Console.WriteLine("Message rotation file successfully written to file");
                }
                else
                {
                    this.SetStatus(DateTime.Now.ToLongTimeString() + ": Write to File Failed");
                    this.SetStatusTextColor(Color.Red);
                    Console.WriteLine("Message rotation was not written to file");
                }
            }
            fdlg.Dispose();
        }

        private void buttonLoadMessageRotation_Click(object sender, EventArgs e)
        {
            if (this.listBoxMessages.Rows.Count > 0)
            {
                if (MessageBox.Show("Loading a config file will overwrite the current rotation, continue?", "Confirm Load", MessageBoxButtons.YesNo) == DialogResult.No)
                    return;
            }
            OpenFileDialog fdlg = new OpenFileDialog();
            fdlg.Title = "Select the Rotation List File";
            fdlg.InitialDirectory = Directory.GetCurrentDirectory();
            fdlg.Filter = "Message Rotation files (*.mer*)|*.mer";
            fdlg.FilterIndex = 1;
            fdlg.RestoreDirectory = true;
            if (fdlg.ShowDialog() == DialogResult.OK)
            {
                this.listBoxMessages.Rows.Clear();
                // Load in contents of file
                List<LuckyBingoRcon.Messages.Message> options = rcon.loadMessageRotationConfig(fdlg.FileName);
                int rowNum = -1;
                foreach (LuckyBingoRcon.Messages.Message entry in options)
                {
                    if (!string.IsNullOrEmpty(entry.GetMessage) && entry.GetDuration > 0 && !string.IsNullOrEmpty(entry.GetGametype) && !string.IsNullOrEmpty(entry.GetMap))
                    {
                        rowNum = this.listBoxMessages.Rows.Add();
                        this.listBoxMessages.Rows[rowNum].Cells[0].Value = entry.GetMessage;
                        this.listBoxMessages.Rows[rowNum].Cells[1].Value = entry.GetDuration;
                        this.listBoxMessages.Rows[rowNum].Cells[2].Value = entry.GetGametype;
                        this.listBoxMessages.Rows[rowNum].Cells[3].Value = entry.GetMap;
                    }
                }
                this.SetStatus(DateTime.Now.ToLongTimeString() + ": Configuration Successfully Loaded from File");
                this.SetStatusTextColor(Color.Green);
                this.buttonUpdateRotation.Enabled = true;
                this.buttonSaveRotation.Enabled = true;
                Console.WriteLine("Message rotation successfully loaded");
            }
            else
            {
                this.SetStatus(DateTime.Now.ToLongTimeString() + ": Configuration Load Failed");
                this.SetStatusTextColor(Color.Red);
                if (this.listBoxMessages.Rows.Count == 0)
                {
                    this.buttonUpdateRotation.Enabled = false;
                    this.buttonSaveRotation.Enabled = false;
                }
                Console.WriteLine("Message rotation load aborted");
            }
            fdlg.Dispose();
            this.checkListBoxMessagesSize();
        }
        #endregion        

        #region Message Field Changes
        private void textboxMessage_TextChanged(object sender, EventArgs e)
        {
            if (this.textboxMessage.Text.Length.Equals(0) || this.textBoxMessageDuration.Text.Length.Equals(0))
                this.buttonAddMessage.Enabled = false;
            else
            {
                try
                {
                    int dur = Convert.ToInt16(this.textBoxMessageDuration.Text);
                    if (dur > 0)
                        this.buttonAddMessage.Enabled = true;
                }
                catch
                {
                    this.buttonAddMessage.Enabled = false;
                }
            }
        }

        private void textBoxMessageDuration_TextChanged(object sender, EventArgs e)
        {
            if (this.textboxMessage.Text.Length.Equals(0) || this.textBoxMessageDuration.Text.Length.Equals(0))
                this.buttonAddMessage.Enabled = false;
            else
            {
                try
                {
                    int dur = Convert.ToInt16(this.textBoxMessageDuration.Text);
                    if (dur > 0)
                        this.buttonAddMessage.Enabled = true;
                }
                catch
                {
                    this.buttonAddMessage.Enabled = false;
                }
            }
        }
        #endregion

        #region Message DataGrid View Changes
        private void listBoxMessages_SelectionChanged(object sender, EventArgs e)
        {
            // For enabling Remove From List Button
            int rowsSelected = this.listBoxMessages.Rows.GetRowCount(DataGridViewElementStates.Selected);
            if (rowsSelected != 0)
            {
                this.buttonRemoveMessage.Enabled = true;
                this.buttonUpdateMessage.Enabled = true;
                DataGridViewRow row = this.listBoxMessages.SelectedRows[0];
                if (row.Cells[0].Value != null && row.Cells[1].Value != null && row.Cells[2].Value != null && row.Cells[3].Value != null)
                {
                    this.textboxMessage.Text = row.Cells[0].Value.ToString();
                    this.textBoxMessageDuration.Text = row.Cells[1].Value.ToString();
                    this.comboBoxGametypeSelect.SelectedIndex = this.comboBoxGametypeSelect.FindStringExact(row.Cells[2].Value.ToString());
                    this.comboBoxMapSelect.SelectedIndex = this.comboBoxMapSelect.FindStringExact(row.Cells[3].Value.ToString());
                }
                this.listBoxMessages.Rows[this.listBoxMessages.SelectedRows[0].Index].Selected = true;
                if (this.listBoxMessages.SelectedRows[0].Index > 0)
                    this.buttonMessageMoveUp.Enabled = true;
                else
                    this.buttonMessageMoveUp.Enabled = false;
                if (this.listBoxMessages.SelectedRows[0].Index < this.listBoxMessages.Rows.Count - 1)
                    this.buttonMessageMoveDown.Enabled = true;
                else
                    this.buttonMessageMoveDown.Enabled = false;
            }
            else
            {
                this.buttonRemoveMessage.Enabled = false;
                this.buttonMessageMoveUp.Enabled = false;
                this.buttonMessageMoveDown.Enabled = false;
                this.buttonUpdateMessage.Enabled = false;
            }
            if (this.listBoxMessages.Rows.Count == 1)
            {
                this.buttonMessageMoveUp.Enabled = false;
                this.buttonMessageMoveDown.Enabled = false;
            }
        }

        private void listBoxMessages_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (this.listBoxMessages.CurrentCell.Value != null)
                this.cellContents = this.listBoxMessages.CurrentCell.Value.ToString();
        }

        private void listBoxMessages_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this.listBoxMessages.CurrentCell.ColumnIndex.Equals(0))
            {
                if (this.listBoxMessages.CurrentCell.Value == null)
                {
                    MessageBox.Show("Must have a string entered here", "Input Error");
                    this.listBoxMessages.CurrentCell.Value = this.cellContents.ToString();
                }
            }
            else if (this.listBoxMessages.CurrentCell.ColumnIndex.Equals(1))
            {
                try
                {
                    int val = Convert.ToInt16(this.listBoxMessages.CurrentCell.Value);
                    if (val <= 0)
                    {
                        MessageBox.Show("Value must be an integer greater than 0", "Input Error");
                        this.listBoxMessages.CurrentCell.Value = this.cellContents.ToString();
                    }
                }
                catch
                {
                    MessageBox.Show("Value must be an integer greater than 0", "Input Error");
                    this.listBoxMessages.CurrentCell.Value = this.cellContents.ToString();
                }
            }
        }
        #endregion

        #region Immediate Console Message
        private void buttonImmediateSay_Click(object sender, EventArgs e)
        {
            if (this.textBoxImmediateMessage.Text.Length > 0)
            {
                rcon.SetSayMessage(this.textBoxImmediateMessage.Text);
                Console.WriteLine("Said: \"" + this.textBoxImmediateMessage.Text + "\" to entire server");
                this.lastMessage = this.textBoxImmediateMessage.Text;
            }
        }

        private void textBoxImmediateMessage_TextChanged(object sender, EventArgs e)
        {
            if (this.textBoxImmediateMessage.Text.Length > 0)
                this.buttonImmediateSay.Enabled = true;
            else
                this.buttonImmediateSay.Enabled = false;
        }
        #endregion

        #region Match List Context & Drag-N-Drop
        private void listBoxMatches_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button.Equals(MouseButtons.Left))
            {
                if (this.listBoxMatches.SelectedIndex != -1)
                {
                    if (this.listBoxMatches.SelectedIndex > 0 && this.listBoxMatches.SelectedIndex < this.listBoxMatches.Items.Count - 1)
                    {
                        Match matchAbove = this.listBoxMatches.Items[this.listBoxMatches.SelectedIndex - 1] as Match;
                        Match matchBelow = this.listBoxMatches.Items[this.listBoxMatches.SelectedIndex + 1] as Match;
                        if (matchAbove.Map.MapName.Equals(matchBelow.Map.MapName))
                        {
                            //MessageBox.Show("You can not move this match because the surrounding matches have the same map selected");
                            return;
                        }
                    }
                    this.clickIndex = this.listBoxMatches.SelectedIndex;
                    this.listBoxMatches.DoDragDrop(this.listBoxMatches.SelectedItem, DragDropEffects.Move);
                }
            }
            else if (e.Button.Equals(MouseButtons.Right))
            {
                Point point = new Point(e.X, e.Y);
                int index = this.listBoxMatches.IndexFromPoint(point);
                this.listBoxMatches.SelectedIndex = index;
                if (!index.Equals(-1))
                    this.contextMenuRemoveMatch.Enabled = true;
                else
                    this.contextMenuRemoveMatch.Enabled = false;
            }
        }

        private void listBoxMatches_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void listBoxMatches_DragDrop(object sender, DragEventArgs e)
        {
            Point point = this.listBoxMatches.PointToClient(new Point(e.X, e.Y));
            int index = this.listBoxMatches.IndexFromPoint(point);
            if (index.Equals(-1))
                index = this.listBoxMatches.Items.Count - 1;
            int oldIndex = this.clickIndex;
            Match selectedMatch = e.Data.GetData(typeof(Match)) as Match;
            this.listBoxMatches.Items.Remove(selectedMatch);
            this.listBoxMatches.Items.Insert(index, selectedMatch);
            if (index != -1)
            {
                if (index < this.listBoxMatches.Items.Count - 1 && this.listBoxMatches.Items[index + 1] is Match)
                {
                    Match matchOneBelow = this.listBoxMatches.Items[index + 1] as Match;
                    if (matchOneBelow.Map.MapName.Equals(selectedMatch.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        this.listBoxMatches.Items.Remove(selectedMatch);
                        this.listBoxMatches.Items.Insert(oldIndex, selectedMatch);
                        return;
                    }
                }
                if (index > 0 && this.listBoxMatches.Items[index - 1] is Match)
                {
                    Match matchOneAbove = this.listBoxMatches.Items[index - 1] as Match;
                    if (matchOneAbove.Map.MapName.Equals(selectedMatch.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        this.listBoxMatches.Items.Remove(selectedMatch);
                        this.listBoxMatches.Items.Insert(oldIndex, selectedMatch); 
                        return;
                    }
                }
            }
            else
            {
                if(this.listBoxMatches.Items.Count > 1)
                {
                    Match matchAbove = this.listBoxMatches.Items[this.listBoxMatches.Items.Count - 2] as Match;
                    if(matchAbove.Map.MapName.Equals(selectedMatch.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        this.listBoxMatches.Items.Remove(selectedMatch);
                        this.listBoxMatches.Items.Insert(oldIndex, selectedMatch); 
                        return;
                    }
                }
                this.listBoxMatches.Items.Remove(selectedMatch);
                this.listBoxMatches.Items.Add(selectedMatch);
            }
            this.listBoxMatches.SelectedIndex = index;
            this.listBoxMatches_SelectedIndexChanged(sender, new EventArgs());
        }

        private void removeMatchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!this.listBoxMatches.SelectedIndex.Equals(-1))
                this.listBoxMatches.Items.RemoveAt(this.listBoxMatches.SelectedIndex);
        }

        private void contextMenuRemoveMatch_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = this.listBoxMatches.SelectedIndex.Equals(-1);
            contextMenuRemoveMatch.Enabled = this.listBoxMatches.Items.Count > 0;
        }
        #endregion

        #region Gametype List Context
        private void contextMenuHideGametype_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = this.listBoxGameTypes.SelectedIndex.Equals(-1);
            contextMenuHideGametype.Enabled = this.listBoxGameTypes.Items.Count > 0;
        }

        private void contextMenuHideGametype_Click(object sender, EventArgs e)
        {
            if (!this.listBoxGameTypes.SelectedIndex.Equals(-1))
                this.listBoxGameTypes.Items.RemoveAt(this.listBoxGameTypes.SelectedIndex);
        }

        private void listBoxGameTypes_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button.Equals(MouseButtons.Right))
            {
                Point point = new Point(e.X, e.Y);
                int index = this.listBoxGameTypes.IndexFromPoint(point);
                this.listBoxGameTypes.SelectedIndex = index;
                if (!index.Equals(-1))
                    this.contextMenuHideGametype.Enabled = true;
                else
                    this.contextMenuHideGametype.Enabled = false;
            }
        }
        #endregion

        #region Map List Context
        private void listBoxMaps_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button.Equals(MouseButtons.Right))
            {
                Point point = new Point(e.X, e.Y);
                int index = this.listBoxMaps.IndexFromPoint(point);
                this.listBoxMaps.SelectedIndex = index;
                if (!index.Equals(-1))
                    this.contextMenuHideMap.Enabled = true;
                else
                    this.contextMenuHideMap.Enabled = false;
            }
        }

        private void contextMenuHideMap_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = this.listBoxMaps.SelectedIndex.Equals(-1);
            contextMenuHideMap.Enabled = this.listBoxMaps.Items.Count > 0;
        }

        private void contextMenuHideMap_Click(object sender, EventArgs e)
        {
            if (!this.listBoxMaps.SelectedIndex.Equals(-1))
                this.listBoxMaps.Items.RemoveAt(this.listBoxMaps.SelectedIndex);
        }
        #endregion

        #region Color Buttons / Color Context
        private void buttonBlackText_Click(object sender, EventArgs e) { insertColorCode("^0"); }
        private void buttonRedText_Click(object sender, EventArgs e) { insertColorCode("^1"); }
        private void buttonGreenText_Click(object sender, EventArgs e) { insertColorCode("^2"); }
        private void buttonYellowText_Click(object sender, EventArgs e) { insertColorCode("^3"); }
        private void buttonBlueText_Click(object sender, EventArgs e) { insertColorCode("^4"); }
        private void buttonCyanText_Click(object sender, EventArgs e) { insertColorCode("^5"); }
        private void buttonMagentaText_Click(object sender, EventArgs e) { insertColorCode("^6"); }
        private void buttonWhiteText_Click(object sender, EventArgs e) { insertColorCode("^7"); }
        private void buttonGreyText_Click(object sender, EventArgs e) { insertColorCode("^8"); }
        private void buttonBrownText_Click(object sender, EventArgs e) { insertColorCode("^9"); }
        private void insertColorCode(string code)
        {
            int pos = this.textbox.SelectionStart;
            this.textbox.Text = this.textbox.Text.Insert(pos, code);
            this.textbox.SelectionStart = pos + 2;
            this.textbox.Focus();
        }

        private void blackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^0");
        }

        private void redToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^1");
        }

        private void greenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^2");
        }

        private void yellowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^3");
        }

        private void blueToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^4");
        }

        private void cyanToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^5");
        }

        private void magentaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^6");
        }

        private void whiteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^7");
        }

        private void greyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^8");
        }

        private void brownToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                insertColorCode("^9");
        }
        #endregion

        #region Message Textbox Context
        private void textboxMessage_MouseDown(object sender, MouseEventArgs e)
        {
            this.textbox = this.textboxMessage;
            this.clickIndex = this.textbox.GetCharIndexFromPosition(new Point(e.X, e.Y));
        }

        private void textBoxImmediateMessage_MouseDown(object sender, MouseEventArgs e)
        {
            this.textbox = this.textBoxImmediateMessage;
            this.clickIndex = this.textbox.GetCharIndexFromPosition(new Point(e.X, e.Y));
        }

        private void selectToBeginningToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                this.textbox.Select(0, this.clickIndex);
        }

        private void selectToEndToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                this.textbox.Select(this.clickIndex, this.textbox.Text.Length - this.clickIndex);
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
            {
                if (this.textbox.SelectionLength > 1)
                    Clipboard.SetDataObject(this.textbox.SelectedText, true);
            }
        }

        private void clearTextToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
            {
                if (this.textbox.SelectionLength > 1)
                {
                    Clipboard.SetDataObject(this.textbox.SelectedText, true);
                    this.textbox.Text = this.textbox.Text.Replace(this.textbox.SelectedText, string.Empty);
                }
            }
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
            {
                IDataObject data = Clipboard.GetDataObject();
                if (data.GetDataPresent(DataFormats.Text))
                    this.textbox.Text = this.textbox.Text.Insert(this.clickIndex, (string)data.GetData(DataFormats.Text));
            }
        }

        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                this.textbox.SelectAll();
        }

        private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null)
                this.textbox.Text = string.Empty;
        }

        private void insertLastMessageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.textbox != null && !this.lastMessage.Equals(String.Empty))
            {
                int pos = this.textbox.SelectionStart;
                this.textbox.Text = this.textbox.Text.Insert(pos, this.lastMessage);
                this.textbox.SelectionStart = pos + this.lastMessage.Length;
                this.textbox.Focus();
            }
        }
        #endregion

        #region Message Drag-N-Drop
        private void listBoxMessages_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button.Equals(MouseButtons.Left))
            {
                if (this.listBoxMessages.SelectedRows.Count != 0)
                    this.listBoxMessages.DoDragDrop(this.listBoxMessages.SelectedRows[0], DragDropEffects.Move);
            }
            else if (e.Button.Equals(MouseButtons.Right))
            {
                int index = this.listBoxMessages.HitTest(e.X, e.Y).RowIndex;
                if (!index.Equals(-1))
                {
                    this.listBoxMessages.CurrentCell = this.listBoxMessages.Rows[index].Cells[0];
                    if (!index.Equals(-1))
                        this.contextMenuRemoveMatch.Enabled = true;
                    else
                        this.contextMenuRemoveMatch.Enabled = false;
                }
            }
        }

        private void listBoxMessages_DragDrop(object sender, DragEventArgs e)
        {
            Point point = this.listBoxMessages.PointToClient(new Point(e.X, e.Y));
            int index = this.listBoxMessages.HitTest(point.X, point.Y).RowIndex;
            DataGridViewRow data = e.Data.GetData(typeof(DataGridViewRow)) as DataGridViewRow;
            this.listBoxMessages.Rows.RemoveAt(this.listBoxMessages.CurrentCell.RowIndex);
            if (index.Equals(-1))
            {
                if (point.Y < 30)
                    index = 0;
                else
                    index = this.listBoxMessages.Rows.Count;
            }
            this.listBoxMessages.Rows.Insert(index, data);
            this.listBoxMessages.CurrentCell = this.listBoxMessages.Rows[index].Cells[0];
        }

        private void listBoxMessages_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }
        #endregion

        #region Player Tab
        private void dataGridViewPlayers_MouseDown(object sender, MouseEventArgs e)
        {
            this.clickIndex = this.dataGridViewPlayers.HitTest(e.X, e.Y).RowIndex;
            if (this.clickIndex.Equals(-1))
            {
                this.playerSayToolStripMenuItem.Enabled = false;
                this.kickPlayerToolStripMenuItem.Enabled = false;
                this.tempBanPlayerToolStripMenuItem.Enabled = false;
                this.banPlayerToolStripMenuItem.Enabled = false;
            }
            else
            {
                this.selectedPlayer = this.dataGridViewPlayers[2, this.clickIndex].Value as string;
                this.playerSayToolStripMenuItem.Enabled = true;
                this.kickPlayerToolStripMenuItem.Enabled = true;
                this.tempBanPlayerToolStripMenuItem.Enabled = true;
                this.banPlayerToolStripMenuItem.Enabled = true;
            }
        }

        private void playerSayToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Point loc = this.Location;
            using (InputBox ib = new InputBox())
            {
                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
            }
            InputResult ir = InputBox.ShowBox("Say To Player", this.selectedPlayer, loc);
            if (ir != null)
            {
                if (!ir.Message.Length.Equals(0))
                {
                    rcon.SetTellMessage(int.Parse(this.dataGridViewPlayers[0, this.clickIndex].Value.ToString()), ir.Message);
                    this.lastMessage = ir.Message;
                    Console.WriteLine("Said: \"" + ir.Message + "\" to: \"" + this.dataGridViewPlayers[2, this.clickIndex].Value.ToString());
                }
            }
        }

        private void sayToAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Point loc = this.Location;
            using (InputBox ib = new InputBox())
            {
                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
            }
            InputResult ir = InputBox.ShowBox("Say To All", this.selectedPlayer, loc);
            if (ir != null)
            {
                if (!ir.Message.Length.Equals(0))
                {
                    rcon.SetSayMessage(ir.Message);
                    this.lastMessage = ir.Message;
                    Console.WriteLine("Said: \"" + ir.Message + "\" to the entire server");
                }
            }
        }
        
        private void kickPlayerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Point loc = this.Location;
            using (InputBox ib = new InputBox())
            {
                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
            }
            InputResult ir = InputBox.ShowBox("Kick Player", this.selectedPlayer, loc);
            if (ir != null)
            {
                if (!ir.Message.Length.Equals(0))
                {
                    rcon.KickClient(int.Parse(this.dataGridViewPlayers[0, this.clickIndex].Value.ToString()), ir.Message);
                    this.lastMessage = ir.Message;
                    Console.WriteLine("Kicked: " + this.dataGridViewPlayers[2, this.clickIndex].Value.ToString() + " - Reason: \"" + ir.Message + "\"");
                }
            }
        }

        private void tempBanPlayerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Point loc = this.Location;
            using (InputBox ib = new InputBox())
            {
                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
            }
            InputResult ir = InputBox.ShowBox("Temp Ban Player", this.selectedPlayer, loc);
            if (ir != null)
            {
                if (!ir.Message.Length.Equals(0))
                {
                    rcon.TempBanClient(int.Parse(this.dataGridViewPlayers[0, this.clickIndex].Value.ToString()), ir.Duration, ir.Message);
                    this.lastMessage = ir.Message;
                    Console.WriteLine("Temp banned: " + this.dataGridViewPlayers[2, this.clickIndex].Value.ToString() + " for " + ir.Duration + " minutes - Reason: \"" + ir.Message + "\"");
                }
            }
        }

        private void banPlayerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            /*Point loc = this.Location;
            using (InputBox ib = new InputBox())
            {
                loc.Offset((this.Width / 2) - (ib.Width / 2), (this.Height / 2) - (ib.Height / 2));
            }
            InputResult ir = InputBox.ShowBox(sender.ToString(), this.selectedPlayer, loc);
            if (ir != null)
            {
                if (!ir.Message.Length.Equals(0))
                {
                    rcon.BanClient(int.Parse(this.dataGridViewPlayers[0, this.clickIndex].Value.ToString()), ir.Message);
                    this.lastMessage = ir.Message;
                    Console.WriteLine("Banned: " + this.dataGridViewPlayers[2, this.clickIndex].Value.ToString() + " - Reason: \"" + ir.Message + "\"");
                }
            }*/
            if (MessageBox.Show("Are you sure you want to ban player: " + this.dataGridViewPlayers[2, this.clickIndex].Value.ToString() + "?", "Ban Player", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                rcon.BanClient(int.Parse(this.dataGridViewPlayers[0, this.clickIndex].Value.ToString()), null);
                Console.WriteLine("Banned: " + this.dataGridViewPlayers[2, this.clickIndex].Value.ToString());
            }
        }
        #endregion

        #region Match ListBox Buttons
        private void buttonMoveItemDown_Click(object sender, EventArgs e)
        {
            int index = this.listBoxMatches.SelectedIndex;
            if (index.Equals(-1))
                return;
            if (index >= this.listBoxMatches.Items.Count)
                return;
            if (this.listBoxMatches.Items[index] is Match)
            {
                Match match = this.listBoxMatches.Items[index] as Match;
                if (this.listBoxMatches.Items.Count > 0 && index < this.listBoxMatches.Items.Count - 2 && this.listBoxMatches.Items[index + 2] is Match)
                {
                    Match matchTwoBelow = this.listBoxMatches.Items[index + 2] as Match;
                    if (matchTwoBelow.Map.MapName.Equals(match.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        return;
                    }
                }
                if (this.listBoxMatches.Items.Count > 0 && index > 0 && this.listBoxMatches.Items[index - 1] is Match)
                {
                    Match matchOneAbove = this.listBoxMatches.Items[index - 1] as Match;
                    Match matchOneBelow = this.listBoxMatches.Items[index + 1] as Match;
                    if (matchOneBelow.Map.MapName.Equals(matchOneAbove.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        return;
                    }
                }
                if (this.listBoxMatches.Items.Count > 0)
                {
                    Match lastMatch = this.listBoxMatches.Items[this.listBoxMatches.Items.Count - 1] as Match;
                    if (lastMatch.Map.MapName.Equals(match.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        return;
                    }
                }
                /*if (this.listBoxMatches.Items.Count > 0)
                {
                    Match lastMatch = this.listBoxMatches.Items[this.listBoxMatches.Items.Count - 1] as Match;
                    if (lastMatch.Map.MapName.Equals(match.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        return;
                    }
                }*/
                this.listBoxMatches.Items.RemoveAt(index);
                this.listBoxMatches.Items.Insert(index + 1, match);
                this.listBoxMatches.SelectedIndex = index + 1;
                this.listBoxMatches_SelectedIndexChanged(sender, e);
            }
        }

        private void buttonMoveItemUp_Click(object sender, EventArgs e)
        {
            int index = this.listBoxMatches.SelectedIndex;
            if (index.Equals(-1))
                return;
            if (index >= this.listBoxMatches.Items.Count)
                return;
            if (this.listBoxMatches.Items[index] is Match)
            {
                Match match = this.listBoxMatches.Items[index] as Match;
                if (this.listBoxMatches.Items.Count > 0 && index > 1 && this.listBoxMatches.Items[index - 2] is Match)
                {
                    Match matchTwoAbove = this.listBoxMatches.Items[index - 2] as Match;
                    if (matchTwoAbove.Map.MapName.Equals(match.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        return;
                    }
                }
                if (this.listBoxMatches.Items.Count > 0 && index < this.listBoxMatches.Items.Count - 1 && this.listBoxMatches.Items[index + 1] is Match)
                {
                    Match matchOneAbove = this.listBoxMatches.Items[index - 1] as Match;
                    Match matchOneBelow = this.listBoxMatches.Items[index + 1] as Match;
                    if (matchOneBelow.Map.MapName.Equals(matchOneAbove.Map.MapName))
                    {
                        MessageBox.Show("You are about to move a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                        return;
                    }
                }
                this.listBoxMatches.Items.RemoveAt(index);
                this.listBoxMatches.Items.Insert(index - 1, match);
                this.listBoxMatches.SelectedIndex = index - 1;
                this.listBoxMatches_SelectedIndexChanged(sender, e);
            }
        }

        private void buttonAddToList_Click(object sender, EventArgs e)
        {
            string map = this.listBoxMaps.Text;
            string uglyName = this.map.GetUglyName(map);
            string game = this.listBoxGameTypes.Text;
            Match newMatch = new Match(new Map(uglyName, map, this.map.GetAbbreviation(uglyName)), new GameType(this.game.GetPlayListNumber(game), game));
            if (this.listBoxMatches.Items.Count > 0)
            {
                Match lastMatch = this.listBoxMatches.Items[this.listBoxMatches.Items.Count - 1] as Match;
                if (lastMatch.Map.MapName.Equals(newMatch.Map.MapName))
                {
                    MessageBox.Show("You are about to add a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                    return;
                }
            }
            this.listBoxMatches.Items.Add(newMatch);
            this.buttonAddToList.Enabled = false;
            this.checkListBoxMatchesSize();
        }

        private void buttonUpdateMatch_Click(object sender, EventArgs e)
        {
            string map = this.listBoxMaps.Text;
            string uglyName = this.map.GetUglyName(map);
            string game = this.listBoxGameTypes.Text;
            int index = this.listBoxMatches.SelectedIndex;
            if (index.Equals(-1))
                return;
            if (index >= this.listBoxMatches.Items.Count)
                return;
            Match newMatch = new Match(new Map(uglyName, map, this.map.GetAbbreviation(uglyName)), new GameType(this.game.GetPlayListNumber(game), game));
            if (this.listBoxMatches.Items.Count > 0 && index < this.listBoxMatches.Items.Count - 1 && this.listBoxMatches.Items[index + 1] is Match)
            {
                Match matchOneBelow = this.listBoxMatches.Items[index + 1] as Match;
                if (matchOneBelow.Map.MapName.Equals(newMatch.Map.MapName))
                {
                    MessageBox.Show("You are about to update a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                    return;
                }
            }
            if (this.listBoxMatches.Items.Count > 0 && index > 0 && this.listBoxMatches.Items[index - 1] is Match)
            {
                Match matchOneAbove = this.listBoxMatches.Items[index - 1] as Match;
                if (matchOneAbove.Map.MapName.Equals(newMatch.Map.MapName))
                {
                    MessageBox.Show("You are about to update a match where the same map runs twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                    return;
                }
            }
            this.listBoxMatches.Items.RemoveAt(index);
            this.listBoxMatches.Items.Insert(index, newMatch);
            this.buttonUpdateMatch.Enabled = false;
        }

        private void buttonRemoveFromList_Click(object sender, EventArgs e)
        {
            int index = this.listBoxMatches.SelectedIndex;
            if (index.Equals(-1))
                return;
            if (index >= this.listBoxMatches.Items.Count)
                return;
            Match remMatch = this.listBoxMatches.Items[index] as Match;
            if (this.listBoxMatches.Items.Count > 0 && index > 0 && this.listBoxMatches.Items[index - 1] is Match && index < this.listBoxMatches.Items.Count - 1 && this.listBoxMatches.Items[index + 1] is Match)
            {
                Match matchOneAbove = this.listBoxMatches.Items[index - 1] as Match;
                Match matchOneBelow = this.listBoxMatches.Items[index + 1] as Match;
                if (matchOneBelow.Map.MapName.Equals(matchOneAbove.Map.MapName))
                {
                    MessageBox.Show("You are about to remove a match to cause the same map to run twice.\nHaving two matches with the same map next to each other will lock the rotation.\nBlocking command", "Match Error");
                    return;
                }
            }
            this.listBoxMatches.Items.RemoveAt(this.listBoxMatches.SelectedIndex);
            this.buttonRemoveFromList.Enabled = false;
            this.buttonMoveItemUp.Enabled = false;
            this.buttonMoveItemDown.Enabled = false;
            this.checkListBoxMatchesSize();
        }

        private void buttonBringToTop_Click(object sender, EventArgs e)
        {
            int index = this.listBoxMatches.SelectedIndex;
            if (!index.Equals(-1))
            {
                Match curMatch;
                while (!index.Equals(0))
                {
                    curMatch = this.listBoxMatches.Items[0] as Match;
                    this.listBoxMatches.Items.Add(curMatch);
                    this.listBoxMatches.Items.RemoveAt(0);
                    index--;
                }
            }
        }
        #endregion

        #region Map ListBox Changes
        private void listBoxGameTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            // For enabling Add To List Button
            if (this.listBoxMaps.SelectedIndex != -1 && this.listBoxGameTypes.SelectedIndex != -1)
            {
                this.buttonAddToList.Enabled = true;
                if (this.listBoxMatches.SelectedIndex != -1)
                    this.buttonUpdateMatch.Enabled = true;
                else
                    this.buttonUpdateMatch.Enabled = false;
            }
            else
                this.buttonAddToList.Enabled = false;
        }

        private void listBoxMaps_SelectedIndexChanged(object sender, EventArgs e)
        {
            // For enabling Add To List Button
            if (this.listBoxMaps.SelectedIndex != -1 && this.listBoxGameTypes.SelectedIndex != -1)
            {
                this.buttonAddToList.Enabled = true;
                if (this.listBoxMatches.SelectedIndex != -1)
                    this.buttonUpdateMatch.Enabled = true;
                else
                    this.buttonUpdateMatch.Enabled = false;
            }
            else
                this.buttonAddToList.Enabled = false;

        }

        private void listBoxMatches_SelectedIndexChanged(object sender, EventArgs e)
        {
            // For enabling Remove From List Button
            if (this.listBoxMatches.SelectedIndex != -1)
            {
                this.buttonRemoveFromList.Enabled = true;
                this.buttonBringToTop.Enabled = true;
                Match selectedMatch = this.listBoxMatches.Items[this.listBoxMatches.SelectedIndex] as Match;
                if (this.listBoxGameTypes.Items.Contains(selectedMatch.GameType.GameName))
                    this.listBoxGameTypes.SetSelected(this.listBoxGameTypes.Items.IndexOf(selectedMatch.GameType.GameName), true);
                if (this.listBoxMaps.Items.Contains(selectedMatch.Map.PrettyName))
                    this.listBoxMaps.SetSelected(this.listBoxMaps.Items.IndexOf(selectedMatch.Map.PrettyName), true);
            }
            else
            {
                this.buttonRemoveFromList.Enabled = false;
                this.buttonBringToTop.Enabled = false;
            }
            if (this.listBoxMatches.Items.Count == 1)
            {
                this.buttonMoveItemUp.Enabled = false;
                this.buttonMoveItemDown.Enabled = false;
            }
            else
            {
                if (this.listBoxMatches.SelectedIndex > 0)
                    this.buttonMoveItemUp.Enabled = true;
                else
                    this.buttonMoveItemUp.Enabled = false;
                if (this.listBoxMatches.SelectedIndex < this.listBoxMatches.Items.Count - 1)
                    this.buttonMoveItemDown.Enabled = true;
                else
                    this.buttonMoveItemDown.Enabled = false;
            }
        }
        #endregion

        #region Check Sizes of Listboxes and Datagridviews
        private void checkListBoxMatchesSize()
        {
            if (this.listBoxMatches.Items.Count == 0)
            {
                this.buttonUpdateRotation.Enabled = false;
                this.buttonSaveRotation.Enabled = false;
                this.contextMenuRemoveMatch.Enabled = false;
                this.clearListToolStripMenuItem.Enabled = false;
            }
            else
            {
                this.buttonUpdateRotation.Enabled = true;
                this.buttonSaveRotation.Enabled = true;
                this.contextMenuRemoveMatch.Enabled = true;
                this.clearListToolStripMenuItem.Enabled = true;
            }
        }

        private void checkListBoxMessagesSize()
        {
            if (this.listBoxMessages.Rows.Count == 0)
            {
                this.buttonUpdateMessageRotation.Enabled = false;
                this.buttonSaveMessageRotation.Enabled = false;
                this.buttonUpdateMessage.Enabled = false;
            }
            else
            {
                this.buttonUpdateMessageRotation.Enabled = true;
                this.buttonSaveMessageRotation.Enabled = true;
            }
        }
        #endregion

        #region Message Add/Remove/Up/Down/Update
        private void buttonAddMessage_Click(object sender, EventArgs e)
        {
            int duration;
            if (!String.IsNullOrEmpty(this.textboxMessage.Text) && int.TryParse(this.textBoxMessageDuration.Text, out duration) == true && duration > 0 && !String.IsNullOrEmpty(this.textBoxMessageDuration.Text))
            {
                DataGridViewRow row = new DataGridViewRow();
                row.CreateCells(this.listBoxMessages);
                LuckyBingoRcon.Messages.Message mess = new LuckyBingoRcon.Messages.Message(this.textboxMessage.Text, Convert.ToInt16(this.textBoxMessageDuration.Text), this.comboBoxGametypeSelect.SelectedItem.ToString(), this.comboBoxMapSelect.SelectedItem.ToString());
                this.listBoxMessages.Rows.Add(mess.ToRow(row));
                this.lastMessage = this.textboxMessage.Text;
            }
            this.checkListBoxMessagesSize();
        }

        private void buttonRemoveMessage_Click(object sender, EventArgs e)
        {
            if (this.listBoxMessages.SelectedRows.Count != 0)
                this.listBoxMessages.Rows.RemoveAt(this.listBoxMessages.SelectedRows[0].Index);
            this.checkListBoxMessagesSize();
        }

        private void buttonMessageMoveUp_Click(object sender, EventArgs e)
        {
            if (this.listBoxMessages.SelectedRows.Count != 0)
            {
                DataGridViewRow row = this.listBoxMessages.SelectedRows[0];
                int rowNum = row.Index;
                if (rowNum > 0)
                {
                    this.listBoxMessages.Rows.RemoveAt(rowNum);
                    this.listBoxMessages.Rows.Insert(rowNum - 1, row);
                    this.listBoxMessages.Rows[rowNum].Selected = false;
                    this.listBoxMessages.Rows[rowNum - 1].Selected = true;
                }
            }
        }

        private void buttonMessageMoveDown_Click(object sender, EventArgs e)
        {
            if (this.listBoxMessages.SelectedRows.Count != 0)
            {
                DataGridViewRow row = this.listBoxMessages.SelectedRows[0];
                int rowNum = row.Index;
                if (rowNum < this.listBoxMessages.Rows.Count - 1)
                {
                    this.listBoxMessages.Rows.RemoveAt(rowNum);
                    this.listBoxMessages.Rows.Insert(rowNum + 1, row);
                    this.listBoxMessages.Rows[rowNum].Selected = false;
                    this.listBoxMessages.Rows[rowNum + 1].Selected = true;
                }
            }
        }

        private void buttonUpdateMessage_Click(object sender, EventArgs e)
        {
            int selectedRows = this.listBoxMessages.Rows.GetRowCount(DataGridViewElementStates.Selected);
            int duration;
            if (selectedRows != 0)
            {
                if (string.IsNullOrEmpty(this.textboxMessage.Text) == false && int.TryParse(this.textBoxMessageDuration.Text, out duration) == true && duration > 0 && this.comboBoxGametypeSelect.SelectedIndex != -1)
                {
                    DataGridViewRow row = this.listBoxMessages.SelectedRows[0];
                    row.Cells[0].Value = this.textboxMessage.Text;
                    row.Cells[1].Value = duration;
                    row.Cells[2].Value = this.comboBoxGametypeSelect.SelectedItem;
                    row.Cells[3].Value = this.comboBoxMapSelect.SelectedItem;
                }
            }
        }
        #endregion

        #region Status
        private void SetStatus(string text)
        {
            if (this.InvokeRequired)
            {
                StringDel d = new StringDel(this.SetStatus);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                toolStripStatusLabel.Text = text;
            }
        }

        private void SetStatusColor(Color color)
        {
            if (this.InvokeRequired)
            {
                ColorDel d = new ColorDel(this.SetStatusColor);
                this.Invoke(d, new object[] { color });
            }
            else
            {
                toolStripStatusLabel.BackColor = color;
            }
        }

        private void SetStatusTextColor(Color color)
        {
            if (this.InvokeRequired)
            {
                ColorDel d = new ColorDel(this.SetStatusTextColor);
                this.Invoke(d, new object[] { color });
            }
            else
            {
                toolStripStatusLabel.ForeColor = color;
            }
        }

        private void ClearStatus()
        {
            if (this.InvokeRequired)
            {
                VoidDel d = new VoidDel(this.ClearStatus);
                this.Invoke(d);
            }
            else
            {
                this.SetStatus("");
            }
        }

        private void SetTextBoxColor(TextBox tb, Color c)
        {
            if (this.InvokeRequired)
            {
                TBoxDel d = new TBoxDel(this.SetTextBoxColor);
                this.Invoke(d, new object[] { tb, c });
            }
            else
            {
                tb.BackColor = c;
            }
        }
        #endregion

        #region Hyperlinks
        private void linkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.net");
            Process.Start(browser);
        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.gameservers.com/clanpay/?clanid=1bd3a3dc454ab2b0dea4851d254632bc");
            Process.Start(browser);
        }
        #endregion

        #region Tab Control
        private void optionTabs_Selecting(object sender, TabControlCancelEventArgs e)
        {
            this.clickIndex = -1;
			if (!rcon.Connected && e.TabPageIndex > 1)
				e.Cancel = true;
			if (e.TabPageIndex > 5 && !this.enableTabs)
				e.Cancel = true;
        }
        #endregion

        #region Form Loading
        private void RconForm_Load(object sender, EventArgs e)                  // Get picture and link working for donation
        {
            this.optionTabs.SelectedIndex = 1;
            
            //this.timerQueue.Enabled = true;
            this.MaximumSize = this.Size;
            this.MinimumSize = this.Size;
            this.MaximizeBox = false;

            this.linkLabel.Links.Remove(linkLabel.Links[0]);
            this.linkLabel.Links.Add(0, linkLabel.Text.Length, "http://www.luckyatbingo.net");

            ToolTip tt = new ToolTip();
            tt.SetToolTip(this.textBoxNextMap, "[Game] = Gametype, [Map] = Map");
            tt.SetToolTip(this.labelCurrentGametype, "This is the last known playlist in the Match rotation.\nIf the list is not being updated, this will be erroneous.");
            tt.AutomaticDelay = 2000;
            tt.AutoPopDelay = 5000;

            this.labelLuckyVersion.Text = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            this.textBoxBuildVersion.Text = "Version " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            this.textBoxBuildDate.Text = "Built on: " + new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).LastWriteTime.ToString("dd MMMM yyyy");

            // Load in Map and Gametype Lists to populate listboxes
            this.listBoxMaps.Items.Clear();
            this.listBoxMaps.Items.AddRange(this.map.GetPrettyNames());
            this.listBoxGameTypes.Items.Clear();
            this.listBoxGameTypes.Items.AddRange(this.game.GetPlayListNames());
            this.comboBoxGametypeSelect.Items.Clear();
            this.comboBoxGametypeSelect.Items.AddRange(this.game.GetUniquePlayListNames());
            this.comboBoxGametypeSelect.SelectedIndex = 0;
            this.comboBoxMapSelect.Items.Clear();
            this.comboBoxMapSelect.Items.Add("Any");
            this.comboBoxMapSelect.Items.AddRange(this.map.GetPrettyNames());
            this.comboBoxMapSelect.SelectedIndex = 0;
            this.listBoxMatches.AllowDrop = true;
            this.listBoxMessages.AllowDrop = true;

            // Set Alignments for DataGridViews and Textboxes
            foreach (DataGridViewColumn col in this.dataGridViewPlayers.Columns)
                col.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            this.dataGridViewPlayers.Columns["columnId"].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            this.dataGridViewPlayers.Columns["columnId"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            this.dataGridViewPlayers.Columns["columnTeam"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            this.dataGridViewPlayers.Columns["columnScore"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            this.dataGridViewPlayers.Columns["columnPing"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            this.dataGridViewPlayers.Columns["columnGUID"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;

            this.listBoxMessages.Columns[1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            this.textBoxNextMapDelay.TextAlign = HorizontalAlignment.Center;

            this.dataGridViewServerVariables.Columns[0].ReadOnly = true;            // Don't want to edit this column

            this.checkListBoxMatchesSize();
            this.checkListBoxMessagesSize();
            Console.WriteLine("Started Lucky Rcon");
        }
        #endregion

        #region Extra Timer
        private void timerQueue_Tick(object sender, EventArgs e)
        {
            /*if (!backWorkAdminCheck.IsBusy)
                backWorkAdminCheck.RunWorkerAsync();*/
        }

        private void backWorkQueue_DoWork(object sender, DoWorkEventArgs e)
        {
            //rcon.GetExcludeMaps();
        }
        #endregion

        #region Memory
        private void timerMemoryCheck_Tick(object sender, EventArgs e)
        {
            this.labelMemoryUsage.Text = (Convert.ToDouble(System.GC.GetTotalMemory(true)) / 1000000).ToString("F3") + " MB";
        }
        #endregion

        #region Admin Checking
        private void checkAdmins_Tick(object sender, EventArgs e)
        {
            if (!this.backWorkAdminCheck.IsBusy)                    // All timers that fire call a background worker to do the processing on another thread
                this.backWorkAdminCheck.RunWorkerAsync();
        }

        private void backWorkAdminCheck_DoWork(object sender, DoWorkEventArgs e)
        {
            rcon.GetServerAdmins();                                 // Either query for time stamp to check if Super Admin (not you) is still responding
            System.Threading.Thread.Sleep(this.delay);              // or submit a new time stamp (you are a super admin) to keep responding
        }

        private void backWorkAdminCheck_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            bool superAdmin = rcon.IsSuperAdmin();                  // Are you a super admin?
            bool oldAdmin = this.enableTabs;                        // Get old super admin status -- same as if you can see all the tabs
            this.enableTabs = superAdmin;                           // Update
            if (oldAdmin.Equals(false) && superAdmin)               // Became a super admin
            {
                MessageBox.Show("You are now a super admin." + Environment.NewLine + "You can adjust the map and message rotations, as well as, other server settings.\nClick \"Start Rotation\" to continue the current Match rotation.", "Admin Change");
                this.listBoxMatches.Items.Clear();                  // Set match list based on given information
                this.listBoxMatches.Items.AddRange(rcon.GetMatches().ToArray());
                this.checkListBoxMatchesSize();
                this.mapCheckTimer.Enabled = true; 
                if (this.listBoxMatches.Items.Count > 0 && this.buttonUpdateRotation.Text.Equals("Start Rotation")) // We have matches ready to go
                    this.buttonUpdateRotation_Click(sender, e);
                Console.WriteLine("Became Super Admin");
            }
            else if (oldAdmin.Equals(true) && !superAdmin)           // This should never happen, lose admin ability
            {
                MessageBox.Show("You are not a super admin anymore.\nYou can only say, kick, and ban.", "Admin Change");
                this.mapCheckTimer.Enabled = false;
                Console.WriteLine("Lost Super Admin privileges");
            }
            else if (!oldAdmin.Equals(superAdmin) && !superAdmin)
            {
                MessageBox.Show("You are a regular admin.\nYou can only say, kick, and ban.", "Admin Privileges");
                this.mapCheckTimer.Enabled = false;
                Console.WriteLine("Became a Regular Admin");
            }
            else if (!oldAdmin.Equals(superAdmin) && superAdmin)
            {
                MessageBox.Show("You are a super admin. You can adjust the map and message rotations, as well as, other server settings.\nClick \"Start Rotation\" to continue the current Match rotation.", "Admin Privileges");
                this.listBoxMatches.Items.Clear();
                this.listBoxMatches.Items.AddRange(rcon.GetMatches().ToArray());
                this.checkListBoxMatchesSize();
                this.mapCheckTimer.Enabled = true;
                if (this.listBoxMatches.Items.Count > 0 && this.buttonUpdateRotation.Text.Equals("Start Rotation")) // We have matches ready to go
                    this.buttonUpdateRotation_Click(sender, e);
                Console.WriteLine("Became a Super Admin");
            }
            if (!this.checkAdmins.Interval.Equals(30000))
                this.checkAdmins.Interval = 30000;
            if (superAdmin)
            {
                this.labelAdminStatus.Text = "Super Admin";
                this.labelAdminStatus.ForeColor = Color.Green;
            }
            else
            {
                this.labelAdminStatus.Text = "Regular Admin";
                this.labelAdminStatus.ForeColor = Color.Orange;
            }
        }
        #endregion

        #region Query Server For dvars, map name, gametype name, server name, etc.
        private void queryServer_Tick(object sender, EventArgs e)
        {
            /*if (!this.backWorkServerInfo.IsBusy)
                this.backWorkServerInfo.RunWorkerAsync();*/
        }

        private void backWorkServerInfo_DoWork(object sender, DoWorkEventArgs e)
        {
            /*rcon.GetServerName();
            System.Threading.Thread.Sleep(this.delay);*/
            /*rcon.GetMapName(this.updateServer);                                 // True == Update Server, if necessary; False == Query map only
            System.Threading.Thread.Sleep(this.delay);*/
            /*rcon.GetPlaylist(this.updateServer);                                // True == Update Server, if necessary; False == Query gametype only
            System.Threading.Thread.Sleep(this.delay);*/
        }

        private void backWorkServerInfo_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //this.queryServerState_Tick(sender, e);                              // Fills in information at top of form
        }
        #endregion

        #region Form Closing
        private void RconForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.buttonConnect.Text.Equals("Disconnect"))
            {
                e.Cancel = true;                                            // Try to close more elegantly, click disconnect, try again
                this.buttonConnect_Click(sender, e);
                MessageBox.Show("Killing all threads first. Close Lucky Rcon again in a moment", "Cannot Close");
                return;
            }
            this.notifyIcon.Visible = false;
        }
        #endregion

        #region Message Display Timer and Worker
        private void messageDisplayTimer_Tick(object sender, EventArgs e)
        {
            if (!this.backWorkDisplayMessage.IsBusy)
            {
                this.messageDisplayTimer.Enabled = false;               // Stop timer until we get another delay for the next message
                this.messageDisplayTimer.Stop();
                this.backWorkDisplayMessage.RunWorkerAsync();
            }
        }

        private void backWorkDisplayMessage_DoWork(object sender, DoWorkEventArgs e)
        {
            int seconds = rcon.displayMessage();                        // Got delay, use RunWorkerCompleted to ensure we get the right int to set
            e.Result = seconds;
        }

        private void backWorkDisplayMessage_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            int seconds = 10;
            if(e != null && e.Result != null)
                seconds = (int)e.Result;
            this.messageDisplayTimer.Interval = seconds * 1000;         // Set delay and start timer
            this.messageDisplayTimer.Enabled = true;
            this.messageDisplayTimer.Start();
        }
        #endregion

        #region Query Players, Update DataGridView
        private void buttonImmediatePlayerUpdate_Click(object sender, EventArgs e)
        {
            queryPlayers_Tick(sender, e);                           // Query players now!
        }

        private void queryPlayers_Tick(object sender, EventArgs e)
        {
            if (!this.backWorkPlayers.IsBusy)
                this.backWorkPlayers.RunWorkerAsync();
        }

        private void backWorkPlayers_DoWork(object sender, DoWorkEventArgs e)
        {
            rcon.GetTeamStatus();                                   // Query for player information
            System.Threading.Thread.Sleep(this.delay);              // To ensure we get some information as fresh as possible (this my still be dated if queue has several items)
        }

        private void backWorkPlayers_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            List<LuckyBingoRcon.Players.Player> players = rcon.GetPlayers();    // Get players
            this.dataGridViewPlayers.Rows.Clear();                  // Clear table
            DataGridViewRow row;
            if (players.Count.Equals(0))                            // Set player count
                this.labelPlayerCount.Text = "0";
            else if (!players[0].SlotID.Equals(0))                  // Demo client not connected
                this.labelPlayerCount.Text = players.Count.ToString();
            else                                                    // Demo client connected
                this.labelPlayerCount.Text = (players.Count - 1).ToString();
            foreach (LuckyBingoRcon.Players.Player player in players)   // Fill in table with players
            {
                row = new DataGridViewRow();
                row.CreateCells(this.dataGridViewPlayers);
                this.dataGridViewPlayers.Rows.Add(player.ToRow(row, this.map.GetUglyName(this.labelCurrentMap.Text)));
            }
        }

        private void textBoxServerUpdateDelay_TextChanged(object sender, EventArgs e)
        {
            int delay = -1;                                         // Time before automated player information update
            if (!this.textBoxServerUpdateDelay.Text.Length.Equals(0) && int.TryParse(this.textBoxServerUpdateDelay.Text, out delay) && delay > 0)
                delay = int.Parse(this.textBoxServerUpdateDelay.Text);
            else
                delay = 30;
            this.textBoxServerUpdateDelay.Text = delay.ToString();
            this.queryPlayers.Interval = delay * 1000;
        }
        #endregion

        #region Display Next Map
        private void displayNextMap_Tick(object sender, EventArgs e)
        {
            if (!this.backWorkDisplayMap.IsBusy)
                this.backWorkDisplayMap.RunWorkerAsync();
        }

        private void backWorkDisplayMap_DoWork(object sender, DoWorkEventArgs e)
        {
            string message = this.textBoxNextMap.Text;              // Get custom text to display to server for next gametype and map
            if (message.Length.Equals(0))
                return;
            ServerState state = rcon.GetServerState();              // Get server information
            if (state != null)
            {
                int index;
                if (state.NextGameType != null)                     // Display gametype, removing the (18) or (12) from the string
                {
                    index = state.NextGameType.IndexOf("(");
                    if (index > 0)
                        message = message.Replace("[Game]", state.NextGameType.Substring(0, index - 1));
                }
                if (state.NextMap != null)                          // Display map
                {
                    message = message.Replace("[Map]", state.NextMap);
                }
            }
            rcon.SetSayMessage(message);                            // Send to server
        }

        private void textBoxNextMapDelay_TextChanged(object sender, EventArgs e)
        {
            int dur = -1;                                           // This should be every couple of minutes to not flood players with next gametype and map
            if (int.TryParse(this.textBoxNextMapDelay.Text, out dur).Equals(false) || dur < 1)
            {
                MessageBox.Show("You have entered an invalid duration." + Environment.NewLine + "Value must be an integer greater than 0", "Input Error");
                this.textBoxNextMapDelay.Text = "120";
                dur = 120;
            }
            this.displayNextMap.Interval = dur * 1000;
        }
        #endregion

        #region Map and Playlist Checks - Timers and Workers
        private void mapCheckTimer_Tick(object sender, EventArgs e)
        {
            if (!this.backWorkMapCheck.IsBusy)
                this.backWorkMapCheck.RunWorkerAsync();
        }

        private void backWorkMapCheck_DoWork(object sender, DoWorkEventArgs e)
        {
            //rcon.GetMapName(this.updateServer);                     // Get map name
            rcon.GetExcludeMaps();
            System.Threading.Thread.Sleep(this.delay);
        }

        private void backWorkMapCheck_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!this.backWorkPlaylistCheck.IsBusy)
                this.backWorkPlaylistCheck.RunWorkerAsync();
        }

        private void backWorkPlaylistCheck_DoWork(object sender, DoWorkEventArgs e)
        {
            rcon.GetPlaylist(this.updateServer);                    // Get gametype
            System.Threading.Thread.Sleep(this.delay);
        }

        private void backWorkPlaylistCheck_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            queryServerState_Tick(sender, e);
        }
        #endregion

        #region Map Rotation Buttons
        private void buttonLoadRotation_Click(object sender, EventArgs e)
        {
            if (this.listBoxMatches.Items.Count > 0)                            // Overwrite current Match list?
            {
                if (MessageBox.Show("Loading a config file will overwrite the current rotation, continue?", "Confirm Load", MessageBoxButtons.YesNo) == DialogResult.No)
                    return;
            }
            OpenFileDialog fdlg = new OpenFileDialog();                         // Open a file dialog window
            fdlg.Title = "Select the Rotation List File";                       // Set some settings for window
            fdlg.InitialDirectory = Directory.GetCurrentDirectory();
            fdlg.Filter = "Match Rotation files (*.mar*)|*.mar*";
            fdlg.FilterIndex = 1;
            fdlg.RestoreDirectory = true;
            if (fdlg.ShowDialog() == DialogResult.OK)                           // User clicked "Ok"
            {
                this.listBoxMatches.Items.Clear();                              // Clear Match list
                // Load in contents of file
                List<Match> matches = rcon.loadMapRotationConfig(fdlg.FileName);
                foreach (Match match in matches)
                {
                    this.listBoxMatches.Items.Add(match);
                }
                this.SetStatus(DateTime.Now.ToLongTimeString() + ": Configuration Successfully Loaded from File");
                Console.WriteLine("Match rotation loaded successfully");
                this.SetStatusTextColor(Color.Green);
                this.buttonUpdateRotation.Enabled = true;
                this.buttonSaveRotation.Enabled = true;
            }
            else
            {
                this.SetStatus(DateTime.Now.ToLongTimeString() + ": Configuration Load Cancelled");
                Console.WriteLine("Match rotation load aborted");
                this.SetStatusTextColor(Color.Red);
                if (this.listBoxMatches.Items.Count == 0)
                {
                    this.buttonUpdateRotation.Enabled = false;
                    this.buttonSaveRotation.Enabled = false;
                }
            }
            fdlg.Dispose();
        }

        private void buttonSaveRotation_Click(object sender, EventArgs e)
        {
            SaveFileDialog fdlg = new SaveFileDialog();                     // Open window to select where to save file
            fdlg.InitialDirectory = Directory.GetCurrentDirectory();
            fdlg.RestoreDirectory = true;
            fdlg.Title = "Select a Location to Save Rotation File";
            fdlg.DefaultExt = "mar";
            fdlg.Filter = "Match Rotation files (*.mar)|*.mar";
            fdlg.FilterIndex = 1;
            fdlg.CheckFileExists = false;
            fdlg.CheckPathExists = true;
            if (fdlg.ShowDialog() == DialogResult.OK)
            {
                bool success = false;
                bool fileValid = false;
                try
                {
                    new FileInfo(fdlg.FileName);
                    fileValid = true;
                }
                catch { }
                if (fileValid)
                {
                    // Save contents of listbox to file
                    List<Match> entries = new List<Match>();
                    Match match;
                    foreach (object item in this.listBoxMatches.Items)
                    {
                        if (item is Match)
                        {
                            match = item as Match;
                            entries.Add(match);
                        }
                    }
                    success = rcon.saveMapRotationConfig(entries, fdlg.FileName);
                }
                if (success)
                {
                    FileInfo fInfo = new FileInfo(fdlg.FileName);
                    fInfo.IsReadOnly = true;
                    this.SetStatus(DateTime.Now.ToLongTimeString() + ": File Successfully Written to File");
                    Console.WriteLine("Match rotation saved successfully");
                    this.SetStatusTextColor(Color.Green);
                }
                else
                {
                    this.SetStatus(DateTime.Now.ToLongTimeString() + ": Write to File Failed");
                    Console.WriteLine("Match rotation write to file failed");
                    this.SetStatusTextColor(Color.Red);
                }
            }
            fdlg.Dispose();
        }

        private void buttonUpdateRotation_Click(object sender, EventArgs e)
        {
            if (this.buttonUpdateRotation.Text.Equals("Start Rotation"))        // Set Match list in RCon backend code
            {
                bool done = false;
                System.Threading.ThreadPool.QueueUserWorkItem((x) =>
                {
                    using (var splash = new splashForm())
                    {
                        Point loc = this.Location;
                        loc.Offset((this.Width / 2) - (splash.Width / 2), (this.Height / 2) - (splash.Height / 2));
                        splash.Location = loc;
                        splash.Show();
                        while (!done)
                            Application.DoEvents();
                        splash.Close();
                    }
                }); 
                /*this.mapCheckTimer.Enabled = false;                             // Turn timers off until list is populated
                this.mapCheckTimer.Stop();*/
                this.updateServer = false;
                List<Match> matches = new List<Match>();
                Match match;
                foreach (object item in this.listBoxMatches.Items)              // Gather match list
                {
                    if (item is Match)
                    {
                        match = item as Match;
                        matches.Add(match);
                    }
                }
                rcon.setGametypeMapLists(matches, true);                              // Set list
                done = true;
                /*this.mapCheckTimer.Enabled = true;                              // Enable / disable controls appopriately
                this.mapCheckTimer.Start();*/
                this.updateServer = true;
                this.listBoxMatches.ClearSelected();
                this.listBoxGameTypes.Enabled = false;
                this.listBoxGameTypes.ClearSelected();
                this.listBoxMaps.Enabled = false;
                this.listBoxMaps.ClearSelected();
                this.buttonAddToList.Enabled = false;
                this.buttonRemoveFromList.Enabled = false;
                this.buttonBringToTop.Enabled = false;
                this.buttonMoveItemDown.Enabled = false;
                this.buttonMoveItemUp.Enabled = false;
                this.buttonLoadRotation.Enabled = false;
                this.listBoxMatches.Enabled = false;
                this.displayNextMap.Enabled = true;
                this.buttonUpdateRotation.Text = "Stop Rotation";
                Console.WriteLine("Match rotation started!");
                if (!this.buttonUpdateMessageRotation.Text.Equals("Stop Rotation") && !this.buttonUpdateRotation.Text.Equals("Stop Rotation"))
                    this.buttonConnect.Enabled = true;
                else
                    this.buttonConnect.Enabled = false;
            }
            else if (this.buttonUpdateRotation.Text.Equals("Stop Rotation"))    // Clear rotation and enable controls
            {
                bool done = false;
                System.Threading.ThreadPool.QueueUserWorkItem((x) =>
                {
                    using (var splash = new splashForm())
                    {
                        Point loc = this.Location;
                        loc.Offset((this.Width / 2) - (splash.Width / 2), (this.Height / 2) - (splash.Height / 2));
                        splash.Location = loc;
                        splash.Show();
                        while (!done)
                            Application.DoEvents();
                        splash.Close();
                    }
                }); 
                /*this.mapCheckTimer.Enabled = false;
                this.mapCheckTimer.Stop();*/
                this.updateServer = false;
                this.buttonUpdateRotation.Text = "Start Rotation";
                rcon.setGametypeMapLists(new List<Match>(), false);
                rcon.SetExcludeMaps(new string[] { "\" \"" }, true);
                done = true;
                MessageBox.Show("Removing excluded map list to prevent locking onto one map", "Clearing Maps");
                this.listBoxGameTypes.Enabled = true;
                this.listBoxMaps.Enabled = true;
                this.buttonLoadRotation.Enabled = true;
                this.listBoxMatches.Enabled = true;
                this.displayNextMap.Enabled = false;
                Console.WriteLine("Match rotation stopped - cleared exclude map list");
                if (!this.buttonUpdateMessageRotation.Text.Equals("Stop Rotation") && !this.buttonUpdateRotation.Text.Equals("Stop Rotation"))
                    this.buttonConnect.Enabled = true;
                else
                    this.buttonConnect.Enabled = false;
            }
        }
        #endregion

        #region Server Variable Tab
        private void backWorkServerDvars_DoWork(object sender, DoWorkEventArgs e)
        {
            bool done = false;
            System.Threading.ThreadPool.QueueUserWorkItem((x) =>
            {
                using (var splash = new splashForm())
                {
                    Point loc = this.Location;
                    loc.Offset((this.Width / 2) - (splash.Width / 2), (this.Height / 2) - (splash.Height / 2));
                    splash.Location = loc;
                    splash.Show();
                    while (!done)
                        Application.DoEvents();
                    splash.Close();
                }
            }); 
            rcon.GetServerVariables();
            System.Threading.Thread.Sleep(this.delay);
            done = true;
        }

        private void buttonQueryVariables_Click(object sender, EventArgs e)
        {
            if (!this.backWorkServerDvars.IsBusy)
                this.backWorkServerDvars.RunWorkerAsync();
        }

        private void backWorkServerDvars_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Dictionary<string, string> vars = rcon.GetVariables();          // Get variables and populate list view
            this.dataGridViewServerVariables.Rows.Clear();
            DataGridViewRow row;
            foreach (KeyValuePair<string, string> kvp in vars)
            {
                row = new DataGridViewRow();
                row.CreateCells(this.dataGridViewServerVariables);
                row.Cells[0].Value = kvp.Key;
                row.Cells[1].Value = kvp.Value;
                this.dataGridViewServerVariables.Rows.Add(row);
            }
        }

        private void buttonUpdateVariable_Click(object sender, EventArgs e)
        {
            if (!this.clickIndex.Equals(-1))
            {
                string val = string.Empty;
                if (this.dataGridViewServerVariables.Rows[this.clickIndex].Cells[1].Value != null)
                    val = this.dataGridViewServerVariables.Rows[this.clickIndex].Cells[1].Value.ToString();     // Value to set
                val = "\"" + val + "\"";
                rcon.SetServerVariable(this.dataGridViewServerVariables.Rows[this.clickIndex].Cells[0].Value.ToString(), val);  // Set variable to value
                Console.WriteLine("Changed: \"" + this.dataGridViewServerVariables.Rows[this.clickIndex].Cells[0].Value.ToString() + "\" to: " + val);
            }
        }

        private void dataGridViewServerVariables_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            this.clickIndex = e.RowIndex;                           // Get row clicked
            if (e.ColumnIndex.Equals(1))                            // Make sure we clicked on an actual value to update
                this.buttonUpdateVariable.Enabled = true;
            else
                this.buttonUpdateVariable.Enabled = false;
        }
        #endregion

        #region System Tray Icon
        private void RconForm_Resize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized == WindowState)
            {
                Hide();
                notifyIcon.BalloonTipTitle = "Lucky Rcon is still running!";
                ServerState state = rcon.GetServerState();
                if (state != null)
                {
                    if (state.ServerName != null)
                        notifyIcon.BalloonTipText = state.ServerName + " is still being controlled";
                    else
                        notifyIcon.BalloonTipText = "Double click the Tomahawks to maximize";
                }
                else
                    notifyIcon.BalloonTipText = "Double click the Tomahawks to maximize";
                notifyIcon.ShowBalloonTip(3000);
            }
        }

        private void notifyIcon_DoubleClick(object sender, EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void notifyIcon_BalloonTipClicked(object sender, EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }
        #endregion

        #region Repainting Characters
        private void labelServerName_Paint(object sender, PaintEventArgs e)
        {
            string message = this.labelServerName.Text;
            if (message != null)
            {
                if (message.Contains("^"))
                {
                    Rectangle newRect = e.ClipRectangle;
                    using (Brush gridBrush = new SolidBrush(this.labelServerName.ForeColor), backColorBrush = new SolidBrush(this.labelServerName.BackColor))
                    {
                        using (Pen gridLinePen = new Pen(gridBrush))
                        {
                            // Erase the cell.
                            e.Graphics.FillRectangle(backColorBrush, newRect);
                            int index = -1;
                            int width = 0;
                            while (!(index = message.IndexOf("^")).Equals(-1))
                            {
                                string color = message.Substring(index, 2);
                                message = message.Remove(index, 2);
                                index = message.IndexOf("^");
                                if (index.Equals(-1))
                                    index = message.Length;
                                TextRenderer.DrawText(e.Graphics, message.Substring(0, index), this.labelServerName.Font, new Point(newRect.X + width, newRect.Y), this.charConverts[color]);
                                width += Convert.ToInt16(Math.Ceiling(e.Graphics.MeasureString(message.Substring(0, index), this.labelServerName.Font).Width));
                                message = message.Remove(0, index);
                            }
                        }
                    }
                }
            }
        }

        private void dataGridViewPlayers_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex.Equals(2) && e.RowIndex > -1)
            {
                if (e.Value != null)
                {
                    string message = e.Value.ToString();
                    if (message.Contains("^"))
                    {
                        int index = -1;
                        int width = 0;
                        e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.ContentForeground);                    
                        while (!(index = message.IndexOf("^")).Equals(-1))
                        {
                            string color = message.Substring(index, 2);
                            message = message.Remove(index, 2);
                            index = message.IndexOf("^");
                            if (index.Equals(-1))
                                index = message.Length;
                            Rectangle r = e.CellBounds;
                            // measure the string
                            SizeF sizeF01 = e.Graphics.MeasureString(message.Substring(0, index), e.CellStyle.Font);
                            Point loc = e.CellBounds.Location;
                            loc.Offset(width, 2);
                            Rectangle r01 = new Rectangle(loc, new Size((int)Math.Ceiling(sizeF01.Width), e.CellBounds.Height));
                            width += (int)Math.Floor(sizeF01.Width);
                            // draw string
                            using (SolidBrush br = new SolidBrush(this.charConverts[color]))
                            {
                                e.Graphics.DrawString(message.Substring(0, index), e.CellStyle.Font, br, r01);
                            }
                            message = message.Substring(index);
                        }
                        e.Handled = true;
                    }
                }
            }
        }

        private void listBoxMessages_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex == 0 && e.RowIndex > -1)
            {
                if (e.Value != null)
                {
                    string message = e.Value.ToString();
                    if (message.Contains("^"))
                    {
                        int index = -1;
                        int width = 0;
                        e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.ContentForeground);
                        while (!(index = message.IndexOf("^")).Equals(-1))
                        {
                            string color = message.Substring(index, 2);
                            message = message.Remove(index, 2);
                            index = message.IndexOf("^");
                            if (index.Equals(-1))
                                index = message.Length;
                            Rectangle r = e.CellBounds;
                            // measure the string
                            SizeF sizeF01 = e.Graphics.MeasureString(message.Substring(0, index), e.CellStyle.Font);
                            Point loc = e.CellBounds.Location;
                            loc.Offset(width + 2, 4);
                            Rectangle r01 = new Rectangle(loc, new Size((int)Math.Ceiling(sizeF01.Width), e.CellBounds.Height));
                            width += (int)Math.Floor(sizeF01.Width);
                            // draw string
                            using (SolidBrush br = new SolidBrush(this.charConverts[color]))
                            {
                                e.Graphics.DrawString(message.Substring(0, index), e.CellStyle.Font, br, r01);
                            }
                            message = message.Substring(index);
                        }
                        e.Handled = true;
                    }
                }
            }
        }
        #endregion

        #region Custom Video Links
        private void linkLabel1_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }

        private void linkLabelIntro_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }

        private void linkLabelRegular_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }

        private void linkLabelSuper_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }

        private void linkLabelMatch_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }

        private void linkLabelMessage_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }

        private void linkLabelMisc_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ProcessStartInfo browser = new ProcessStartInfo("http://www.luckyatbingo.clanservers.com/forum/YaBB.pl");
            Process.Start(browser);
        }
        #endregion

        #region Custom Commands
        private void textBoxConsoleCommand_TextChanged(object sender, EventArgs e)
        {
            if (this.textBoxConsoleCommand.Text.Length > 0)
            {
                this.buttonSendCommand.Enabled = true;
                this.AcceptButton = this.buttonSendCommand;
            }
            else
            {
                this.buttonSendCommand.Enabled = false;
                this.AcceptButton = null;
            }
        }

        private void buttonSendCommand_Click(object sender, EventArgs e)
        {
            string command = this.textBoxConsoleCommand.Text;
            this.textBoxConsoleCommand.Text = string.Empty;
            if (!command.Contains(" "))
                this.listBoxConsoleCommands.Items.Add("Request:\t" + command);
            else
                this.listBoxConsoleCommands.Items.Add("Sent:\t" + command);
            Thread t = new Thread(new ParameterizedThreadStart(rcon.SendCustomCommand));
            t.Start(command);
            this.textBoxConsoleCommand.Text = string.Empty;
        }

		private delegate void CustomCommandDelegate(object sender, Commands.Events.CustomCommandEventArgs e);

		private void customCommand_OnResponse(object sender, Commands.Events.CustomCommandEventArgs e)
		{
			if (base.InvokeRequired)
			{
				CustomCommandDelegate d = new CustomCommandDelegate(customCommand_OnResponse);
				base.Invoke(d, new object[] { sender, e });
			}
			else
			{
				string response = e.RawResponse;
				if (response != null)
				{
					response = response.Replace("print", "");
					string[] resp = response.Replace("\n", "\t").Split(new string[] { "\r" }, StringSplitOptions.RemoveEmptyEntries);
					this.listBoxConsoleCommands.Items.AddRange(resp);
					if (!this.customCommands.Contains(this.textBoxConsoleCommand.Text))
					{
						this.customCommands.Add(this.textBoxConsoleCommand.Text);
						this.customCommandCounter++;
					}
				}
			}
		}

        private void buttonClearConsole_Click(object sender, EventArgs e)
        {
            this.listBoxConsoleCommands.Items.Clear();
        }

        private void textBoxConsoleCommand_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue.Equals(38) && this.customCommandCounter > -1)
            {
                if (this.customCommandCounter > 0)
                {
                    this.customCommandCounter--;
                    this.textBoxConsoleCommand.Text = this.customCommands[this.customCommandCounter];
                }
                else
                {
                    this.customCommandCounter = this.customCommands.Count - 1;
                    this.textBoxConsoleCommand.Text = this.customCommands[this.customCommandCounter];
                }
            }
            else if (e.KeyValue.Equals(40) && this.customCommandCounter > -1)
            {
                if (this.customCommandCounter < this.customCommands.Count - 1)
                {
                    this.customCommandCounter++;
                    this.textBoxConsoleCommand.Text = this.customCommands[this.customCommandCounter];
                }
                else
                {
                    this.customCommandCounter = 0;
                    this.textBoxConsoleCommand.Text = this.customCommands[this.customCommandCounter];
                }
            }
        }
        #endregion

        private void clearListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to clear the match list?", "Input Required", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                this.listBoxMatches.Items.Clear();
                rcon.setGametypeMapLists(new List<Match>(), true);
                this.checkListBoxMatchesSize();
            }
        }

        private void buttonUnstickMapList_Click(object sender, EventArgs e)
        {
            if(MessageBox.Show("You are about to clear the next map in the rotation.\nYou should only need to do this if the server is stuck on one map.\nThe rotation will continue after a random map is selected.\nAre you sure you want to clear the next map?", "Clear Map Rotation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                rcon.SetExcludeMaps(new string[] { "\" \"" }, true);
        }
    }
}